/* 
LRU & LFU local memory cache
 */

#include <unistd.h>
#include <ck_pr.h>
#ifndef LL_CACHE_H_INCLUDED
#define LL_CACHE_H_INCLUDED

#define CACHENDEBUG

/* system includes */

#include <pthread.h>

#include <stdint.h>
#include <sys/types.h>

#define LL_CACHE_MIN_VALUES (1024)
#define LL_CACHE_DEFAULT_MAX_VALUES (128*1024)

#define LL_CACHE_MIN_SIZE (64)
#define LL_CACHE_DEFAULT_MAX_SIZE (4*1024)

#define LL_CACHE_FLAG_NONE (0)
#define LL_CACHE_FLAG_DONT_FREE (1<<1)
#define LL_CACHE_FLAG_DONT_LOCK (1<<2)

typedef struct _ll_cache ll_cache_t;
typedef struct _ll_cache_entry ll_cache_entry_t;

typedef size_t(*ll_cache_size_func) (void *);
typedef int (*ll_cache_compare_func) (void *, void *);
typedef void (*ll_cache_destroy_func) (void *);
typedef void (*ll_cache_missing_func) (void *);
typedef void (*ll_cache_xchain_func) (void *,unsigned int);

struct _ll_cache_entry {
	time_t mtime;					  /* last modification time */
	unsigned access;
	char *key;						  /* copy of original key */
	void *value;					  /* pointer to value */

	ll_cache_entry_t *prev;		  /* previous entry in lru cache */
	ll_cache_entry_t *next;		  /* next entry in lru cache */
};

struct _ll_cache {
	time_t mtime;					/* last modification time, used to invalidate cache entries */
	int ttl;						/* time to live in seconds */

	uint32_t seed;
	size_t max_size;
	size_t size_cnt;
	unsigned int max_values;

	ll_cache_entry_t **values;
	/* first and last pointers are used for least recently used logic */

	pthread_rwlock_t *entry_lock;

#ifdef  _PTHREAD_POOL_H
   struct pthreadpool_t *cache_pool;
#endif
	unsigned int *value_cnt;

	ll_cache_size_func size_func;
	ll_cache_compare_func compare_func;
	ll_cache_destroy_func destroy_func;
	ll_cache_missing_func destroy_func;
	ll_cache_xchain_func xchain_func;
};

ll_cache_t *ll_cache_create(unsigned int, unsigned int, int *);

int ll_cache_empty(ll_cache_t *, int, int *);
int ll_cache_destroy(ll_cache_t *, int, int *);

/* cache CAN'T be locked externally, this is usefull when you need to be sure
   that the data will be valid throughout your function */
//int ll_cache_rdlock (ll_cache_t *, int *);
//int ll_cache_wrlock (ll_cache_t *, int *);
//int ll_cache_unlock (ll_cache_t *, int *);

void *ll_cache_get(ll_cache_t *, char *, int, int *);
int ll_cache_set(ll_cache_t *, char *, void *, int, int *);
int ll_caceh_unset(ll_cache_t *, char *, int, int *);

#endif
